<template>
	<view class="grid" :class="getGridClass" v-if="list.length > 0 && vertical">
		<view class="grid-border" @touchmove="touchMove" @touchstart="touchStart" @touchend="touchEnd">
			<view class="grid-inner" id="grid" :style="{ transform: `translate3d(${position}rpx, 0, 0)`, 'transition-duration': `${duration}ms`, 'transition-timing-function': bezier }">
				<view v-for="(item, index) in list" :key="index" @click="itemTouhEnd(item)" class="grid-info" :style="{ width: `${ceilWidth}rpx` }">
					<image :src="item[imageField]" mode="aspectFill"></image>
					<view class="text">{{ item[nameField] }}</view>
				</view>
			</view>
		</view>
		<view class="bottom" v-if="list.length > size">
			<view class="pull-left"></view>
			<view class="indicate" :style="{ width: `${Math.ceil(list.length / size) * 30}rpx` }">
				<view
					class="bar"
					:style="{
						transform: `translate3d(${Math.ceil(Math.abs(indicatePosition) / width) * 30}rpx, 0, 0)`,
						'transition-duration': `${duration}ms`,
						'transition-timing-function': bezier
					}"
				></view>
			</view>
			<view class="pull-right"></view>
		</view>
	</view>
	<view class="grid" :class="getGridClass" v-else-if="list.length > 0" @touchmove.stop.prevent>
		<view class="grid-border" @touchmove="touchMove" @touchstart="touchStart" @touchend="touchEnd">
			<view class="grid-inner" id="grid" :style="{ transform: `translate3d(${position}rpx, 0, 0)`, 'transition-duration': `${duration}ms`, 'transition-timing-function': bezier }">
				<view v-for="(item, index) in list" :key="index" @click="itemTouhEnd(item)" class="grid-info" :style="{ width: `${ceilWidth}px` }">
					<image :src="item[imageField]" mode="aspectFill"></image>
					<view class="text">{{ item[nameField] }}</view>
				</view>
			</view>
		</view>
		<view class="bottom" v-if="list.length > size">
			<view class="pull-left"></view>
			<view class="indicate" :style="{ width: `${Math.ceil(list.length / size) * 30}rpx` }">
				<view
					class="bar"
					:style="{
						transform: `translate3d(${Math.ceil(Math.abs(indicatePosition) / width) * 30}rpx, 0, 0)`,
						'transition-duration': `${duration}ms`,
						'transition-timing-function': bezier
					}"
				></view>
			</view>
			<view class="pull-right"></view>
		</view>
	</view>
</template>

<script>
export default {
	props: {
		shadowBar: { type: Boolean, default: false },
		size: { type: Number, default: 4 },
		list: {
			type: Array,
			default() {
				return [];
			}
		},
		imageField: { type: String, default: 'iconImgUrl' },
		nameField: { type: String, default: 'iconName' }
	},
	computed: {
		getGridClass() {
			const showIndicate = this.list.length > this.size ? 'show-indicate' : '';
			const shadowBar = this.shadowBar ? 'shadow-bar' : '';
			return [showIndicate, shadowBar].join(' ');
		}
	},
	watch: {
		list: {
			handler(lst) {
				if (lst && lst.length) {
					const query = uni.createSelectorQuery().in(this);
					this.$nextTick(() => {
						query
							.select('#grid')
							.boundingClientRect(({ width }) => {
								this.width = width * this.ratio;
								this.ceilWidth = width / this.size;
								this.moveMax = this.width - (this.width / this.size) * lst.length;
							})
							.exec();
					});
				}
			},
			deep: true,
			immediate: true
		}
	},
	data() {
		const info = uni.getSystemInfoSync();
		return {
			ratio: 750 / info.windowWidth,
			width: 0,
			moveMax: 0,
			ceilWidth: 0,
			position: 0,
			indicatePosition: 0,
			duration: 0,
			bezier: 'linear',
			vertical: false,
			horizion: false
		};
	},
	methods: {
		itemTouhEnd(item) {
			setTimeout(() => {
				if (Math.abs(this.move || 0) < 10) {
					this.$emit('click', item);
				}
			}, 0);
		},
		touchStart({ touches }) {
			if (this.list.length > this.size) {
				this.allowMove = true;
				this.duration = 0;
				const { pageX,pageY } = touches[0];
				this.startX = pageX * this.ratio;
				this.startY = pageY;
				this.current = this.position;
			}
		},
		touchMove({ touches }) {
			if (this.allowMove) {
				const { pageX, pageY } = touches[0];
				this.move = pageX * this.ratio - this.startX;
				
				if (!this.horizion && !this.vertical && this.move !== 0) {
					this.horizion = true;
				}
				if (!this.horizion && !this.vertical && this.pageY - this.startY !== 0) {
					this.vertical = true;
				}
				if (this.horizion) {
					this.position = this.current + this.move;
				} else {
					this.allowMove = false;
				}
			}
		},
		touchEnd({ touches }) {
			if (this.allowMove) {
				this.allowMove = false;
				this.duration = 200;
				this.bezier = 'cubic-bezier(.25, .46, .45, .94)';
				let current = this.position - this.move;
				if (Math.abs(this.move) > this.width / this.size / 2) {
					if (this.move < 0) {
						current += -this.width;
					} else {
						current += +this.width;
					}
				}
				this.position = current > 0 ? 0 : current < this.moveMax ? this.moveMax : current;
				this.indicatePosition = this.position;

				setTimeout(() => {
					//重置
					this.move = 0;
					this.startX = 0;
					this.current = 0;
					this.duration = 0;
					this.bezier = 'linear';
				}, 300);
			}
		}
	}
};
</script>

<style scoped lang="less">
.grid {
	background: #fff;
	position: relative;
	user-select: none;
	&.shadow-bar {
		box-shadow: 0rpx 8rpx 20rpx 0rpx rgba(102, 100, 93, 0.2);
		border-radius: 12rpx;
	}
	&.show-indicate {
		padding-bottom: 20rpx;
		.bottom {
			margin-top: 10rpx;
		}
	}

	.grid-border {
		margin: 0 26rpx;
		overflow: hidden;
		.grid-inner {
			white-space: nowrap;
			-webkit-overflow-scrolling: touch;
			overflow-scrolling: touch;
			will-change: transform;
			.grid-info {
				text-align: center;
				min-width: 160rpx;
				margin: 20rpx 0;
				display: inline-block;
				align-items: center;
				image {
					user-select: none;
					width: 70rpx;
					height: 70rpx;
					margin-bottom: 4rpx;
					border-radius: 50%;
					// box-shadow: 0 10rpx 15rpx 0rpx rgba(0, 0, 0, 0.12);
				}
				.text {
					font-size: 22rpx;
					font-weight: 400;
					color: #66645d;
					line-height: 30rpx;
				}
			}
		}
	}
	.bottom {
		position: relative;
		left: 50%;
		transform: translateX(-50%);
		display: flex;
		align-items: center;
		justify-content: center;
		.pull-left {
			width: 20rpx;
			height: 12rpx;
			background: url(//mall-rongchuang.oss-cn-beijing.aliyuncs.com/guixin_miniProgram/img/pull_left_icon.png) no-repeat;
			background-size: 20rpx 12rpx;
		}
		.indicate {
			width: 30rpx;
			height: 8rpx;
			border-radius: 8rpx;
			background-color: rgba(138, 140, 141, 0.2);
			margin: 0 16rpx;
			.bar {
				background-color: #f39800;
				width: 30rpx;
				height: 8rpx;
				border-radius: 8rpx;
			}
		}
		.pull-right {
			width: 20rpx;
			height: 12rpx;
			background: url(//mall-rongchuang.oss-cn-beijing.aliyuncs.com/guixin_miniProgram/img/pull_right_icon.png) no-repeat;
			background-size: 20rpx 12rpx;
		}
	}
}
</style>
